package com.nuoniu.sibanyun.service.po.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.result.HttpResult;
import com.nuoniu.sibanyun.entity.erp.ErpNumberSet;
import com.nuoniu.sibanyun.entity.po.VPoPurchaseOrderMain;
import com.nuoniu.sibanyun.entity.po.VRoRequisitionOrderDetail;
import com.nuoniu.sibanyun.entity.po.VRoRequisitionOrderMain;
import com.nuoniu.sibanyun.entity.production.MaMrpDetail;
import com.nuoniu.sibanyun.entity.production.VProductionPlanDetail;
import com.nuoniu.sibanyun.entity.production.VProductionWorkDetail;
import com.nuoniu.sibanyun.mapper.erp.ErpNumberSetMapper;
import com.nuoniu.sibanyun.mapper.po.VRoRequisitionOrderMainMapper;
import com.nuoniu.sibanyun.mapper.production.VProductionPlanDetailMapper;
import com.nuoniu.sibanyun.service.crm.ICrmGoodsService;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpNumberSetService;
import com.nuoniu.sibanyun.service.po.IVPoPurchaseOrderMainService;
import com.nuoniu.sibanyun.service.po.IVRoRequisitionOrderDetailService;
import com.nuoniu.sibanyun.service.po.IVRoRequisitionOrderMainService;
import com.nuoniu.sibanyun.service.production.IMaMrpDatailService;
import com.nuoniu.sibanyun.service.production.IVProductionPlanDetailService;
import com.nuoniu.sibanyun.service.utils.ErpUtils;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 请购单主表 服务实现类
 * </p>
 *
 * @author baiqiang
 * @since 2020-11-17
 */
@Service
public class VRoRequisitionOrderMainServiceImpl extends ServiceImpl<VRoRequisitionOrderMainMapper, VRoRequisitionOrderMain> implements IVRoRequisitionOrderMainService {

    @Autowired
    private IErpNumberSetService numberSetService;
    @Autowired
    private IVRoRequisitionOrderDetailService requisitionOrderDetailService;
    @Autowired
    private IErpAccountService erpAccountService;
    @Autowired
    private ErpNumberSetMapper numberSetMapper;
    @Autowired
    private ICrmGoodsService crmGoodsService;
    @Autowired
    private VProductionPlanDetailMapper productionPlanDetailMapper;
    @Autowired
    private IVPoPurchaseOrderMainService purchaseOrderMainService;
    @Autowired
    private IMaMrpDatailService maDetailService;
    @Autowired
    private IVProductionPlanDetailService productionPlanDetailService;

    @Override
    public String getCode(Integer companyId) {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        ErpNumberSet numberSet = numberSetMapper.getByCode("PurchaseRequisition", companyId, currentAccountId);
        String dateStr = numberSet.getMedian() == 1 ? "%Y-%m-%d" : "%Y-%m";
        String code = baseMapper.getCode(companyId, dateStr);
        return numberSetService.getCode(numberSet, code);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveOrder(VRoRequisitionOrderMain requisitionOrderMain) {
        if(requisitionOrderMain.getOrderDetailList() == null || requisitionOrderMain.getOrderDetailList().size() == 0) {
            throw new NuoNiuException("请购单明细不能为空");
        }

        if(requisitionOrderMain.getId() != null) {
            List<VPoPurchaseOrderMain> vPoPurchaseOrderMains = purchaseOrderMainService.getBySourceCode(requisitionOrderMain.getSourceVoucherCode());
            if(vPoPurchaseOrderMains.size() > 0) {
                throw new NuoNiuException("已生成采购单,不能修改");
            }
        }

        List<VRoRequisitionOrderDetail> orderDetailList = requisitionOrderMain.getOrderDetailList();
        if(null == orderDetailList)throw new NuoNiuException("单据明细不能为空");
        Long mainId = requisitionOrderMain.getId();
        UserInfo userInfo = UserThreadLocal.get();
        if(mainId == null) {
            String code = getCode(userInfo.getCompanyId());
            if(code == null) {
                throw new NuoNiuException("单据编号已上限");
            }
            boolean isHaveId = orderDetailList.stream().anyMatch(f -> null != f.getId());
            if(isHaveId)throw new NuoNiuException("单据明细错误：不能新增已经存在的明细记录");
            boolean isHaveInventoryId = orderDetailList.stream().anyMatch(f -> null == f.getInventoryId());
            if(isHaveInventoryId)throw new NuoNiuException("单据明细错误：物料参数错误");
            requisitionOrderMain.setVoucherState(-1);
            requisitionOrderMain.setVoucherCode(code);
            requisitionOrderMain.setAccountId(erpAccountService.getCurrentAccountId());
            requisitionOrderMain.setCompanyId(userInfo.getCompanyId());
            requisitionOrderMain.setCreateUserId(userInfo.getUserId());
            requisitionOrderMain.setCreateUserName(userInfo.getRealName());
            requisitionOrderMain.setCumExecuteQuantity(new BigDecimal(0.0));
        } else {
            //校验详情（详情不能有其他单据的明细ID）
            boolean isHaveErrorId = orderDetailList.stream().anyMatch(f -> null != f.getOrderId() && !mainId.toString().equals(f.getOrderId().toString()));
            if(isHaveErrorId)throw new NuoNiuException("单据明细错误：不能修改其他单据的明细记录");
            VRoRequisitionOrderMain requisitionOrder = this.getById(mainId);
            Integer voucherState = requisitionOrder.getVoucherState();
            if(voucherState != null && voucherState > 0) {
                throw new NuoNiuException("已审核,不能修改");
            }
            /**************  修改权限 *******************/
            if(!crmGoodsService.isHaveOperationRight(requisitionOrder.getCreateUserId().longValue())){
                throw new NuoNiuException("你没有权限操作该记录");
            }
            requisitionOrderMain.setUpdateUserId(userInfo.getUserId());
            requisitionOrderMain.setUpdateUserName(userInfo.getRealName());
            requisitionOrderMain.setAccountId(requisitionOrder.getAccountId());
        }

        // 校验 明细数量
        boolean isOk = requisitionOrderMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
        if(isOk)throw new NuoNiuException("明细数量必须大于0");
        // 计算 明细物料 总数
        BigDecimal totalQuantity =  requisitionOrderMain.getOrderDetailList().stream().map(VRoRequisitionOrderDetail::getBaseQuantity).reduce(BigDecimal.ZERO,BigDecimal::add);
        requisitionOrderMain.setTotalQuantity(totalQuantity.abs());
        //保存单据主表
        boolean result = this.saveOrUpdate(requisitionOrderMain);
        if(result) {
            List<Long> detailIds = new ArrayList<>();
            orderDetailList.forEach(p -> {
                p.setCompanyId(userInfo.getCompanyId());
                p.setOrderId(requisitionOrderMain.getId().intValue());
                p.setAccountId(requisitionOrderMain.getAccountId());
                if(p.getId() != null) {
                    detailIds.add(p.getId());
                } else if(p.getSourceDetailId() != null) {
                    if(requisitionOrderMain.getSourceVoucherType().equals("MasterProductionSchedule")) {
                        VProductionPlanDetail detail = productionPlanDetailMapper.selectById(p.getSourceDetailId());
                        BigDecimal releasedQuantity = baseMapper.getReleasedQuantity(p.getSourceDetailId(), p.getId());
                        releasedQuantity = releasedQuantity == null ? new BigDecimal(0.0) : releasedQuantity;
                        if(releasedQuantity.add(p.getBaseQuantity()).compareTo(detail.getBaseQuantity()) > 0) {
                            throw new NuoNiuException("下达数量不能超过计划数量");
                        }
                        if(!detail.getReleaseState().equals(3)) {
                            if(detail.getReleasedQuantity().add(p.getBaseQuantity()).compareTo(detail.getBaseQuantity()) > -1) {
                                detail.setReleaseState(3);
                            } else {
                                detail.setReleaseState(2);
                            }
                            detail.setReleasedQuantity(releasedQuantity.add(p.getBaseQuantity()));
                            productionPlanDetailMapper.updateById(detail);
                        }
                    }
                }
            });

            //删除明细
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("order_id", mainId);
            if(detailIds.size() > 0) {
                wrapper.notIn("id", detailIds);
            }

            requisitionOrderDetailService.remove(wrapper);
            //保存单据明细表
            requisitionOrderDetailService.saveOrUpdateBatch(orderDetailList);
        }
    }

    @Override
    public void submit(Long id, Integer status) {
        if(null == id || null == status || (null != status && (status > 0 || status < -1 )))throw new NuoNiuException("参数错误");
        UserInfo userInfo = UserThreadLocal.get();
        VRoRequisitionOrderMain requisitionOrderMain = this.getById(id);
        if( null == requisitionOrderMain)throw new NuoNiuException("记录不存在");
        //校验状态
        Integer voucherState = requisitionOrderMain.getVoucherState();
        if(status == 0){
            if (voucherState > -1)throw new NuoNiuException("该单据已经提交");
        }else if(status == -1){
            if (voucherState > 0)throw new NuoNiuException("该单据已经审核,请先弃审");
        }
        //提交
        requisitionOrderMain.setVoucherState(status);
        requisitionOrderMain.setSubmitDate(LocalDateTime.now());
        requisitionOrderMain.setSubmitUserId(userInfo.getUserId());
        requisitionOrderMain.setSubmitUserName(userInfo.getRealName());
        this.updateById(requisitionOrderMain);
    }

    @Override
    public void examine(Long id, Integer status) {
        UserInfo userInfo = UserThreadLocal.get();
        VRoRequisitionOrderMain requisitionOrderMain = this.getById(id);
        if(requisitionOrderMain == null) {
            throw new NuoNiuException("单据不存在");
        }
        /**************  修改权限 *******************/
        Integer voucherState = requisitionOrderMain.getVoucherState();
        BigDecimal cumExecuteQuantity = requisitionOrderMain.getCumExecuteQuantity();
        /** 统一校验 审核状态*/
        ErpUtils.checkExamineStatus(voucherState,status,cumExecuteQuantity);
        requisitionOrderMain.setVoucherState(status);
        requisitionOrderMain.setReviewerUserId(userInfo.getUserId());
        requisitionOrderMain.setReviewerUserName(userInfo.getRealName());
        requisitionOrderMain.setReviewerDate(LocalDateTime.now());
        this.updateById(requisitionOrderMain);
    }

    @Override
    public void deleteById(Long id) {
        VRoRequisitionOrderMain requisitionOrderMain = this.getById(id);
        if (requisitionOrderMain == null) {
            throw new NuoNiuException("已删除");
        }
        if(!requisitionOrderMain.getCreateUserId().equals(UserThreadLocal.get().getUserId())) {
            throw new NuoNiuException("你只能删除自己的数据");
        }

        List<VPoPurchaseOrderMain> vPoPurchaseOrderMains = purchaseOrderMainService.getBySourceCode(requisitionOrderMain.getVoucherCode());
        if(vPoPurchaseOrderMains.size() > 0) {
            throw new NuoNiuException("已生成采购单,不能删除");
        }

        //如果有来源单据，恢复下达数量
        if(requisitionOrderMain.getSourceVoucherId() != null && requisitionOrderMain.getSourceVoucherType() != null) {
            List<MaMrpDetail> orderDetails   = maDetailService.getDetailByManId(id);
            //恢复下达数量
            orderDetails.forEach(o -> {
                if(o.getSourceDetailId() != null && o.getBaseQuantity() != null) {
                    if(requisitionOrderMain.getSourceVoucherType().equals("RequirementPlan")) { //物料需求计划
                        maDetailService.updateReleasedQuantityReduce(o.getSourceDetailId(), o.getBaseQuantity());
                    } else if(requisitionOrderMain.getSourceVoucherType().equals("MasterProductionSchedule")) { //主生产计划
                        productionPlanDetailService.updateReleasedQuantityReduce(o.getSourceDetailId(), o.getBaseQuantity());
                    }
                }
            });
        }

        this.removeById(id);
        requisitionOrderDetailService.removeByOrderId(id);
    }


}
